package com.five.welcome.controller;

import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.five.welcome.config.AliPayConfig;
import com.five.welcome.entity.Orders;
import com.five.welcome.service.OrdersService;
import com.five.welcome.service.WelcomeProgressService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.five.welcome.constant.payStatusConstant;
import com.alipay.api.internal.util.AlipaySignature;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝支付控制器
 */
@CrossOrigin
@Slf4j
@RestController
@RequestMapping("/alipay")
public class AliPayController {

    // 支付宝沙箱网关地址
    private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    private static final String FORMAT = "JSON";
    private static final String CHARSET = "UTF-8";
    private static final String SIGN_TYPE = "RSA2";

    @Autowired
    private AliPayConfig aliPayConfig;

    @Autowired
    private OrdersService ordersService;

    @Autowired
    private WelcomeProgressService welcomeProgressService;

    @GetMapping("/pay")
    public void pay(@RequestParam String orderId, HttpServletResponse httpResponse) {
        try {
            // 查询订单信息
            Orders orders = ordersService.getOrderByOrderId(orderId);
            if (orders == null) {
                httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "订单不存在");
                return;
            }

            // 1. 创建Client，通用SDK提供的Client，负责调用支付宝的API
            AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                    aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);

            // 2. 创建 Request并设置Request参数
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            request.setReturnUrl("http://localhost:5173/reportAll/toPay");
            request.setNotifyUrl(aliPayConfig.getNotifyUrl());

            JSONObject bizContent = new JSONObject();
            bizContent.set("out_trade_no", orders.getOrderId());
            bizContent.set("total_amount", orders.getTotal());
            bizContent.set("subject", orders.getName());
            bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY");
            log.info(bizContent.toString());
            request.setBizContent(bizContent.toString());

            /*request.setBizContent("{\"out_trade_no\":\"" + orderId + "\","
                    + "\"total_amount\":\"" + orders.getTotal() + "\","
                    + "\"subject\":\"" + orders.getName() + "\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");*/

            // 执行请求，拿到响应的结果，返回给浏览器
            String form = alipayClient.pageExecute(request).getBody();
            httpResponse.setContentType("text/html;charset=" + CHARSET);
            httpResponse.getWriter().write(form);
            httpResponse.getWriter().flush();
            httpResponse.getWriter().close();
        } catch (AlipayApiException e) {
            log.error("支付接口调用失败: {} - {}", e.getErrCode(), e.getErrMsg(), e);
            try {
                httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "支付接口调用失败: " + e.getErrMsg());
            } catch (IOException ioException) {
                log.error("响应错误", ioException);
            }
        } catch (IOException e) {
            log.error("IO异常", e);
            try {
                httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "IO异常: " + e.getMessage());
            } catch (IOException ioException) {
                log.error("响应错误", ioException);
            }
        }
    }

    @PostMapping("/notify")
    public void payNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
            }
            // 验证签名
            boolean checkSignature = AlipaySignature.rsaCheckV1(params, aliPayConfig.getAlipayPublicKey(), CHARSET, SIGN_TYPE);
            log.error(request.getParameter("trade_status"));
            if (checkSignature) {
                if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
                    log.info("=========支付宝异步回调========");

                    log.info("交易名称: " + params.get("subject"));
                    log.info("交易状态: " + params.get("trade_status"));
                    log.info("支付宝交易凭证号: " + params.get("trade_no"));
                    log.info("商户订单号: " + params.get("out_trade_no"));
                    log.info("交易金额: " + params.get("total_amount"));
                    log.info("买家在支付宝唯一id: " + params.get("buyer_id"));
                    log.info("买家付款时间: " + params.get("gmt_payment"));
                    log.info("买家付款金额: " + params.get("buyer_pay_amount"));

                    String tradeNo = params.get("out_trade_no");
                    String gmtPayment = params.get("gmt_payment");
                    String alipayTradeNo = params.get("trade_no");

                    Orders orders = ordersService.getOrderByOrderId(tradeNo);
                    orders.setPayStatus(payStatusConstant.PAYED);
                    orders.setPayTime(gmtPayment);
                    orders.setPayNo(alipayTradeNo);
                    ordersService.updateByOrderId(orders);

                    welcomeProgressService.updateValue("payed", orders.getSNumber());
                }
            } else {
                log.warn("验签失败");
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "验签失败");
            }
        } catch (Exception e) {
            log.error("异步回调处理失败", e);
            try {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "异步回调处理失败: " + e.getMessage());
            } catch (IOException ioException) {
                log.error("响应错误", ioException);
            }
        }
    }
}
